/*
    SUSAN® - Sole of Unix Save ANything

   Copyright (C) 2004-2007 Hechzh Property
   Copyright (C) 2016-2020 Hechzh Property

   
*/
/*
 * Written by Meno Abels, June MMIV
 */
/**
 * @file
 * address configuration
 */

#include "lib/dlist.h"

class OutputFormatterResource;

/* clang-format off */
class IPADDR {
 public:
  typedef enum
  {
    R_SINGLE,
    R_SINGLE_PORT,
    R_SINGLE_ADDR,
    R_MULTIPLE,
    R_DEFAULT,
    R_EMPTY,
    R_UNDEFINED
  } i_type;
  IPADDR(int af);
  IPADDR(const IPADDR& src);

 private:
  IPADDR();
  i_type type = R_UNDEFINED;
  union {
    struct sockaddr dontuse;
    struct sockaddr_in dontuse4;
#ifdef HAVE_IPV6
    struct sockaddr_in6 dontuse6;
#endif
  } saddrbuf;
  struct sockaddr* saddr = nullptr;
  struct sockaddr_in* saddr4 = nullptr;
#ifdef HAVE_IPV6
  struct sockaddr_in6* saddr6 = nullptr;
#endif
 public:
  void SetType(i_type o);
  i_type GetType() const;
  unsigned short GetPortNetOrder() const;
  unsigned short GetPortHostOrder() const { return ntohs(GetPortNetOrder()); }
  void SetPortNet(unsigned short port);
  int GetFamily() const;
  struct sockaddr* get_sockaddr();
  int GetSockaddrLen();
  void CopyAddr(IPADDR* src);
  void SetAddrAny();
  void SetAddr4(struct in_addr* ip4);
#ifdef HAVE_IPV6
  void SetAddr6(struct in6_addr* ip6);
#endif
  const char* GetAddress(char* outputbuf, int outlen);
  void BuildConfigString(OutputFormatterResource& send,
                                      bool inherited);
  const char* build_address_str(char* buf, int blen, bool print_port = true);

  /* private */
  dlink link;
};
/* clang-format on */

void InitDefaultAddresses(dlist** addr, const char* port);
void FreeAddresses(dlist* addrs);

const char* GetFirstAddress(dlist* addrs, char* outputbuf, int outlen);
int GetFirstPortNetOrder(dlist* addrs);
int GetFirstPortHostOrder(dlist* addrs);

int AddAddress(dlist** out,
               IPADDR::i_type type,
               unsigned short defaultport,
               int family,
               const char* hostname_str,
               const char* port_str,
               char* buf,
               int buflen);
const char* BuildAddressesString(dlist* addrs,
                                 char* buf,
                                 int blen,
                                 bool print_port = true);

int SockaddrGetPortNetOrder(const struct sockaddr* sa);
int SockaddrGetPort(const struct sockaddr* sa);
char* SockaddrToAscii(const struct sockaddr* sa, char* buf, int len);
#ifdef WIN32
#undef HAVE_OLD_SOCKOPT
#endif
#ifdef HAVE_OLD_SOCKOPT
int inet_aton(const char* cp, struct in_addr* inp);
#endif
